package cn.turboinfo.dongying.api.domain.common.handler.rule.impl;

import cn.turboinfo.dongying.api.domain.common.handler.rule.IRuleGroupCollectionFilter;
import cn.turboinfo.dongying.api.domain.util.BeanHelper;
import cn.turboinfo.dongying.api.entity.common.enumeration.rule.RuleControlType;
import cn.turboinfo.dongying.api.entity.common.enumeration.rule.control.CollectionOrderControl;
import cn.turboinfo.dongying.api.entity.common.pojo.rule.RuleGroup;
import cn.turboinfo.dongying.api.entity.common.pojo.rule.RuleItem;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Random;

@Slf4j
@RequiredArgsConstructor
@Component
public class CollectionOrderRuleGroupFilter implements IRuleGroupCollectionFilter {

    @Override
    public RuleControlType getType() {
        return RuleControlType.COLLECTION_ORDER;
    }

    @Override
    public <T> List<T> filterCollection(List<T> elementList, RuleGroup ruleGroup, Object controlObject) {
        if (elementList.isEmpty()) {
            return elementList;
        }

        List<RuleItem> itemList = ruleGroup.getItemList();

        List<T> filterList = elementList;
        for (RuleItem ruleItem : itemList) {
            try {
                CollectionOrderControl control = CollectionOrderControl.get(ruleItem.getLabelValue());

                switch (control) {
                    case Limit:
                        filterList = filterList.subList(0, Math.min(Integer.parseInt(ruleItem.getControlValue()), elementList.size()));
                        break;
                    case OrderStrategy:
                        // 排序方式 目前只支持随机
                        if (StringUtils.equalsIgnoreCase(ruleItem.getControlValue(), "random")) {
                            Collections.shuffle(filterList, new Random());
                        } else {
                            // 排序规则格式 fieldA>|fieldB<|fieldC  大于号表示降序 小于号表示升序 默认升序可省略 多个字段用 | 隔开
                            String[] sortFields = StringUtils.split(ruleItem.getControlValue(), "|");
                            // 保持顺序, 升序 True 降序 False
                            LinkedHashMap<String, Boolean> sortFieldMap = new LinkedHashMap<>();
                            for (String sortField : sortFields) {
                                if (sortField.endsWith(">")) {
                                    sortFieldMap.put(StringUtils.substringBeforeLast(sortField, ">"), false);
                                } else {
                                    sortFieldMap.put(StringUtils.substringBeforeLast(sortField, "<"), true);
                                }
                            }
                            filterList.sort((o1, o2) -> {
                                for (String property : sortFieldMap.keySet()) {
                                    // 分别获取两个对象的属性
                                    Object p1 = BeanHelper.deepGetPropertySilently(o1, property);
                                    Object p2 = BeanHelper.deepGetPropertySilently(o2, property);

                                    if (p1 == null && p2 == null) {
                                        // 都为 null 继续比较下一个排序条件
                                        continue;
                                    }

                                    if (p1 != null && p2 == null) {
                                        // 非 null 排在 null 之前
                                        return -1 * (sortFieldMap.get(property) ? 1 : -1);
                                    }

                                    if (p1 == null) {
                                        // 非 null 排在 null 之前
                                        return (sortFieldMap.get(property) ? 1 : -1);
                                    }

                                    // 如果当前属性都不为空且可比 进行比较
                                    if (p1 instanceof Comparable && p2 instanceof Comparable) {
                                        @SuppressWarnings("unchecked")
                                        int result = ((Comparable<Object>) p1).compareTo(p2);
                                        if (result != 0) {
                                            return result * (sortFieldMap.get(property) ? 1 : -1);
                                        }
                                    }

                                }

                                return 0;
                            });
                        }
                        break;
                }
            } catch (Exception e) {
                log.error("处理规则条目出错", e);
            }
        }

        return filterList;
    }
}
